#include "../include/defs.h"
#include "../include/strings.h"
#include "../include/kasm.h"
#include "../include/gdt.h"


extern DESCR_SEG gdt[MAXDESCGDT];			/* GDT de 255 entradas*/
extern GDTR gdtr;


int inicializarGdt(void){

    // Carga de GDTR    
	print("Inicializando GDT...\n\0");
	//Creo una gdtr auxiliar
	GDTR auxGdt;
	
	//inicializo el registro de la GDT
	gdtr.base = 0;  
	gdtr.base +=(dword) &gdt;
	gdtr.limit = sizeof(gdt)-1;
	
	//Recupero el actual registro de la GDT
	_sgdt(&auxGdt);
	
	copyMem(&gdt,(char*)auxGdt.base,(sizeof(gdt[0]) *5));
	_lgdt(&gdtr);

	cargaGdt(0xb8000,0xfffff, 0,0,1, 0, 6);
	
	print("GDT Inicializada correctamente\n\0");

}


void * setMem(void * dest, char c, int count)
{
	  char* p = (char*)dest;

	while (count--)
		*p++ = c;

	return dest;
}
void copyMem(void * dest, void * src, int count)
{
	char* pSrc = (char*)src;
	char* pDest = (char*)dest;

	while (count--)
		*(pDest++) = *(pSrc++);

 	return;
}

void
cargaGdt(unsigned int dirBase,unsigned int limite, unsigned int  dpl,unsigned int s,unsigned int e, unsigned int g, int indice)
{
	int atributos=0;
	if(indice > 0 && indice < MAXDESCGDT)
	{  
	      gdt[indice].attribs=0;
	      
	      gdt[indice].base_l = (dirBase & 0xffff);
	      gdt[indice].base_m = (dirBase>>16);
	      gdt[indice].base_h = (dirBase>>24);
	      
	      atributos |= 128;
	      atributos |= (dpl<<5);
	      atributos |= (s<<4);
	      if(e==0)
		      atributos |= ACS_CODE;
	      else
		      atributos |= ACS_DATA;
	      gdt[indice].access=atributos;
	      gdt[indice].limit=limite;
	      if(g==1)
		      gdt[indice].attribs|= 0x80;
	      gdt[indice].attribs|=(limite>>16);
	}
}

void
standartGdt(int ind, STANDARTGDT * aux )
{	unsigned int dirBaseh,dirBasem,dirBasel, limh;
	
	aux->dirBase=0;
	aux->limite=0;
  
	dirBasel=gdt[ind].base_l;
	dirBasel &= 0xffff;
	dirBasem=(gdt[ind].base_m<<16);
	dirBaseh=(gdt[ind].base_h<<24);
	aux->dirBase = dirBasel + dirBaseh + dirBasem;
	
	limh=(gdt[ind].attribs & 15);
	aux->limite=gdt[ind].limit;
	aux->limite|=(limh<<16);
	(aux->limite) &= 0xfffff;
	
	if(((gdt[ind].access)& 8) == 0)
		aux->E=0;
	else
		aux->E=1;
	if((gdt[ind].attribs & 0x80) == 0)
		aux->G=0;
	else
		aux->G=1;
	aux->C=gdt[ind].access & 4;
	  
	aux->A=gdt[ind].access & 1;
}
int memWrite(int dsc, unsigned int offset, char * src, int count){
      STANDARTGDT aux;
      standartGdt(dsc, &aux);
      copyMem((char*)(aux.dirBase + offset),src,count);
      return count;
}

int memRead(int dsc, unsigned int offset, int count){
      
    char buffer[count];
    STANDARTGDT aux;
    standartGdt(dsc, &aux);
    copyMem( buffer, (char*)(aux.dirBase +offset),count);
    print(buffer);
    return count;
  
}


